package com.example.bootintegration.controller;

import com.example.bootintegration.dao.test.entity.Student;
import com.example.bootintegration.dao.test.repository.StudentRepositorytest;
import com.example.bootintegration.entity.Order;
import com.example.bootintegration.entity.Person;
import com.example.bootintegration.entity.User;
import com.example.bootintegration.instrument.DynamicTest;
import com.example.bootintegration.listener.BaseEvent;
import com.example.bootintegration.service.RedisTemplateTest;
import com.example.bootintegration.service.RetryTest;
import com.example.bootintegration.service.TransactionTest;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.core.instrument.Metrics;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Quintoy
 * @date 01/02/23
 */
@RestController
@RestControllerAdvice
@Log4j2
public class IndexController {

    @Autowired
    private StudentRepositorytest studentRepositorytest;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private TransactionTest test;
    @Autowired
    private RetryTest retryTest;
    @Autowired
    private RedisTemplateTest redisTemplateTest;
    @Autowired
    private HttpServletResponse servletResponse;


    @GetMapping("/test_params")
    public String test_get(User user) {
        return "succ";
    }




    @GetMapping("/dynamicReg")
    public String reg(@RequestParam String name) {
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ((GenericApplicationContext) applicationContext).getBeanFactory();
        try {
            Class<?> aClass = ClassUtils.forName(name, Thread.currentThread().getContextClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        BeanDefinitionBuilder xx = BeanDefinitionBuilder.genericBeanDefinition(name);
        beanFactory.registerBeanDefinition(name, xx.getBeanDefinition());
        return "succ";
    }

    @GetMapping("/exe")
    public void test(@RequestParam String name) {
        ParentStragery bean = (ParentStragery)applicationContext.getBean(name);
        bean.execute();
    }

    @GetMapping("/testRedis")
    public void redis(@RequestParam String name) {
        redisTemplateTest.clearCache();
    }


    @Autowired
    private ObjectMapper objectMapper;

    @GetMapping("/testJacon")
    public void testJacon() {
        //
        User user = new User();
        user.setAmount(new BigDecimal("111111.2222222222222222222222"));
        Map map = objectMapper.convertValue(user, Map.class);
        System.out.println(map);
    }



    @GetMapping("/publishEvent")
    public void publishEvent() {
        // applicationContext.publishEvent(new RegisterSuccessEvent("歪歪"));
        applicationContext.publishEvent(new BaseEvent(new Person("personxx"), "add"));
        applicationContext.publishEvent(new BaseEvent(new Order("orderxxx"), "add"));
    }

    @GetMapping("/servlet")
    public void servlettest(HttpServletRequest request, HttpServletResponse response) {
        try {

            System.out.println("hello world123");
            new DynamicTest().test();
            response.getWriter().print("hello world");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @GetMapping("/test_time")
    public void testTime(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("testtime");
        Map<String, Object> map = new HashMap<>();
        map.put("date", new Date());
        PrintWriter writer = response.getWriter();
        TimeUnit.SECONDS.sleep(5);
        writer.println("hello world");
        writer.println("hello world");
        writer.println("hello world");
        writer.flush();
        System.out.println("end...");

        // return map;
    }

    // @Bean
    // public ObjectMapper objectMapper() {
    //     ObjectMapper mapper = new ObjectMapper();
    //     mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
    //     return mapper;
    // }
    //
    // @Bean
    // public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
    //     FastJsonHttpMessageConverter fastJsonHttpMessageConvert = new FastJsonHttpMessageConverter();
    //     FastJsonConfig config = new FastJsonConfig();
    //     config.setDateFormat("yyyy-MM-dd:HH");
    //     fastJsonHttpMessageConvert.setFastJsonConfig(config);
    //     return fastJsonHttpMessageConvert;
    // }




    @Autowired
    TransactionTest transactionTest;

    @GetMapping("/index")
    // @Log("hello")
    public List<Student> index(String name) {
        // test.addPerson();
        // return studentRepositorytest.findAll();
        transactionTest.test_deleteAndSave();
        return null;
    }

    @GetMapping("/exception")
    public Object IndexController() {
        System.out.println("test.controller...");
        int i = 1 / 0;
        return "hello";
    }

    @GetMapping("/metrics")
    public void hello() {
        Metrics.gauge("user.test.gauge", 3);
    }


    @GetMapping("/retry")
    public void retry() throws Exception {
        // int i = 1 / 0;
        // retryTest.testRetry();
        ServletOutputStream outputStream = servletResponse.getOutputStream();
        outputStream.println("hello world");
        outputStream.flush();
        TimeUnit.SECONDS.sleep(2);

        outputStream.println("hello world2");
        outputStream.flush();
        TimeUnit.SECONDS.sleep(2);
        outputStream.println("hello world3");
        log.info("exit.....");
    }

    @GetMapping("/timeout")
    public void timeout() throws IOException, InterruptedException {
        PrintWriter writer = servletResponse.getWriter();
        writer.println("hello world");
        TimeUnit.SECONDS.sleep(3);
        writer.println("xxxxxx");
        writer.flush();

    }

    @GetMapping("/sse")
    public SseEmitter sse() {
        SseEmitter emitter = new SseEmitter();
        try {
            emitter.send(SseEmitter.event().name("message").data("hello world"));
            TimeUnit.SECONDS.sleep(2);
            emitter.send(SseEmitter.event().name("message").data("hello world2"));
            TimeUnit.SECONDS.sleep(2);
            emitter.send(SseEmitter.event().name("message").data("hello world3"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return emitter;
    }

    @GetMapping("/stream")
    public void stream(HttpServletResponse response) throws IOException, InterruptedException {
        response.setContentType("text/plain");
        response.setHeader("Cache-Control", "no-cache");
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.print("hello world");
        outputStream.flush();
        TimeUnit.SECONDS.sleep(2);

        outputStream.print("hello world2");
        outputStream.flush();
        TimeUnit.SECONDS.sleep(2);

        outputStream.print("hello world3");
        outputStream.flush();
    }


}
